package mint.modules.generator.expression;

import java.util.ArrayList;
import java.util.Formatter;
import java.util.List;

import mint.modules.generator.Scope;
import mint.modules.symbol.Symbol;
import mint.modules.symbol.SymbolType;
import mint.modules.type.Type;
import mint.modules.type.TypeId;

import org.antlr.runtime.tree.Tree;

public class ArrayCreationExprNode extends Expression {
	private Type baseType;	
	private int line;
	private List<String> errors;
	private List<Expression> exprList;

	public ArrayCreationExprNode(Scope theParent, ExpressionType exprType, Tree arrayCreationTree) {
		super(theParent, exprType);
		baseType = Type.getTypeFromTree(arrayCreationTree.getChild(0));
		exprList = new ArrayList<Expression>();		
		errors = new ArrayList<String>();
		line = arrayCreationTree.getLine();
		
		for (int i = 1; i < arrayCreationTree.getChildCount(); i++)
		{
			Tree child = arrayCreationTree.getChild(i);
			
			exprList.add(new ExprNode(theParent, ExpressionType.Right, child.getChild(0)));
		}
	}

	@Override
	public void testSemantic() {
		if (getExpressionType() == ExpressionType.Left || getExpressionType() == ExpressionType.RightLeft)
			errors.add(line + ": array creation expression must be on the right side of a assignation");
		else if (baseType.getTypeId() == TypeId.Object && !baseType.equals(Type.stringType))
		{
			Symbol symbol = searchSymbol(baseType.getName());
			
			if (symbol == null)
				errors.add(line + ": The class " + baseType.getCompleteName() + " doesn't exist");
			else
				if (symbol.getSymbolType() != SymbolType.Class)
					errors.add(line + ": " + baseType.getCompleteName() + " isn't a class name");
		}
				
		for(Expression expr : exprList)
		{
			expr.testSemantic();
			
			if (!expr.getType().equals(Type.intType))
			{
				errors.add(expr.getLine() + ": expression closed between [] must be int type");
			}
		}
	}

	@Override
	public List<String> getSemanticErrors() {
		for(Expression expr : exprList)
		{
			errors.addAll(expr.getSemanticErrors());
		}		
		return errors;
	}

	@Override
	public void emit(Formatter output) {
		//expr.emit(output);
		for(Expression expr : exprList)
			expr.emit(output);
		
		if (exprList.size() <= 1)
		{
			if (baseType.getTypeId() == TypeId.Primitive)
				output.format("newarray %s\n", baseType.emitTypeName());
			else
				output.format("anewarray %s\n", baseType.emitTypeName());
		} else
		{
			output.format("multianewarray ");
			for(int i = 0; i < exprList.size(); i++)
				output.format("[");
			output.format("%s %d\n", baseType.emit(), exprList.size());
		}
	}
	
	@Override
	public int getLine() {
		return line;
	}

	@Override
	public Type getType() {		
		return Type.createArrayFromType(baseType, exprList.size());
	}

	@Override
	public void leftEmit(Formatter output) {}

}
